﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace JoyServer
{
	/// <summary>
	/// ActionScript3 の flash.utils.ByteArray と同じ働きをするクラス
	/// 圧縮機能と writeObject(), readObject() は未実装
	/// </summary>
	public class ByteArray
	{
		/// <summary>
		/// 書き込んだデータの保存用
		/// </summary>
		private MemoryStream data;

		/// <summary>
		/// MemoryStream に接続するリーダー
		/// </summary>
		private BinaryReader reader;

		/// <summary>
		/// MemoryStream に接続するライター
		/// </summary>
		private BinaryWriter writer;

		/// <summary>
		/// コンストラクタ
		/// </summary>
		public ByteArray()
		{
			data = new MemoryStream();
			reader = new BinaryReader(data);
			writer = new BinaryWriter(data);
		}

		/// <summary>
		/// 書き込み済みのデータ量 (バイト単位)
		/// </summary>
		public uint length
		{
			get { return (uint)data.Length; }
		}

		/// <summary>
		/// 現在のヘッド位置 (読み書き用)
		/// </summary>
		public uint position
		{
			get { return (uint)data.Position; }
			set { data.Position = value; }
		}

		/// <summary>
		/// データのクリア
		/// </summary>
		public void clear()
		{
			data.Close();
			data = new MemoryStream();
			reader = new BinaryReader(data);
			writer = new BinaryWriter(data);
		}

		/// <summary>
		/// 書き込んだ内容をバイト配列で取得する
		/// </summary>
		/// <returns></returns>
		public byte[] toBytes()
		{
			data.Position = 0;
			return reader.ReadBytes((int)data.Length);
		}


		public sbyte readByte()
		{
			return reader.ReadSByte();
		}

		public byte readUnsignedByte()
		{
			return reader.ReadByte();
		}

		public void readBytes(ByteArray bytes, uint offset, uint length)
		{
			bytes.writeBytes(this, offset, length);
		}

		public bool readBoolean()
		{
			return reader.ReadBoolean();
		}

		public short readShort()
		{
			return reader.ReadInt16();
		}

		public ushort readUnsignedShort()
		{
			return reader.ReadUInt16();
		}

		public int readInt()
		{
			return reader.ReadInt32();
		}

		public uint readUnsignedint()
		{
			return reader.ReadUInt32();
		}

		public float readFloat()
		{
			return reader.ReadSingle();
		}

		public double readDouble()
		{
			return reader.ReadDouble();
		}

		public String readUTF()
		{
			ushort length = reader.ReadUInt16();
			byte[] bytes = reader.ReadBytes(length);
			return Encoding.UTF8.GetString(bytes);
		}

		public String readUTFBytes(uint length)
		{
			byte[] bytes = reader.ReadBytes((int)length);
			return Encoding.UTF8.GetString(bytes);
		}


		public void writeByte(sbyte value)
		{
			writer.Write(value);
		}

		public void writeUnsignedByte(byte value)
		{
			writer.Write(value);
		}

		public void writeBytes(ByteArray bytes, uint offset, uint length)
		{
			bytes.reader.BaseStream.Position = offset;
			writer.Write(bytes.reader.ReadBytes((int)length));
		}

		public void writeBytes(byte[] bytes)
		{
			writer.Write(bytes);
		}

		public void writeBoolean(bool value)
		{
			writer.Write(value);
		}

		public void writeShort(short value)
		{
			writer.Write(value);
		}

		public void writeInt(int value)
		{
			writer.Write(value);
		}

		public void writeUnsignedint(uint value)
		{
			writer.Write(value);
		}

		public void writeFloat(float value)
		{
			writer.Write(value);
		}

		public void writeDouble(double value)
		{
			writer.Write(value);
		}

		public void writeUTF(String value)
		{
			byte[] bytes = Encoding.UTF8.GetBytes(value);

			if (bytes.Length > 0xFFFF)
				return;

			ushort length = (ushort)bytes.Length;
			writer.Write(length);
			writer.Write(bytes);
		}

		public void writeUTFBytes(String value)
		{
			byte[] bytes = Encoding.UTF8.GetBytes(value);
			writer.Write(bytes);
		}
	}
}
